package com.xuecheng.teaching.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.teaching.model.dto.WorkDTO;
import com.xuecheng.api.teaching.model.qo.QueryWorkModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.teaching.agent.ContentApiAgent;
import com.xuecheng.teaching.common.constant.TeachingErrorCode;
import com.xuecheng.teaching.convert.WorkConvert;
import com.xuecheng.teaching.entity.Work;
import com.xuecheng.teaching.entity.WorkRecord;
import com.xuecheng.teaching.mapper.WorkMapper;
import com.xuecheng.teaching.service.WorkRecordService;
import com.xuecheng.teaching.service.WorkService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 作业 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class WorkServiceImpl extends ServiceImpl<WorkMapper, Work> implements WorkService {

    @Autowired
    private ContentApiAgent contentApiAgent;

    @Autowired
    private WorkRecordService workRecordService;

    /**
     * <p>
     * 根据作业id查询作业信息
     * </p>
     *
     * @param workId 作业id
     * @return WorkDTO
     */
    @Override
    public WorkDTO getWorkById(Long workId, Long companyId) {

        Work work = this.getById(workId);
        if (ObjectUtils.isEmpty(work)) {
            ExceptionCast.cast(TeachingErrorCode.E_130304);
        }
        if (!ObjectUtils.nullSafeEquals(companyId, work.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }

        return WorkConvert.INSTANCE.workToDTO(work);
    }

    /**
     * <p>
     * 微服务调用 查询作业信息
     * </p>
     *
     * @param workId 作业id
     * @return RestResponse<WorkDTO>
     */
    @Override
    public RestResponse<WorkDTO> getByWorkId(Long workId) {

        Work work = this.getById(workId);
        WorkDTO workDTO;
        if (ObjectUtils.isEmpty(work)) {
            RestResponse.validfail(TeachingErrorCode.E_130304);
        }
        workDTO = WorkConvert.INSTANCE.workToDTO(work);

        return RestResponse.success(workDTO);
    }

    /**
     * <p>
     *
     * </p>
     *
     * @param params
     * @param model
     * @param companyId
     * @return PageVO<WorkDTO>
     */
    @Override
    public PageVO<WorkDTO> queryWorkList(PageRequestParams params, QueryWorkModel model, Long companyId) {

        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        //正则校验页码合法性
        if (isNotPositiveNumeric(pageNo.toString())) {
            pageNo = PageRequestParams.DEFAULT_PAGE_NUM;
        }
        if (isNotPositiveNumeric(pageSize.toString())) {
            pageSize = PageRequestParams.DEFAULT_PAGE_SIZE;
        }
        //构建分页对象
        Page<Work> pageRequest = new Page<>(pageNo, pageSize);

        //构建条件参数
        LambdaQueryWrapper<Work> queryWrapper = Wrappers.lambdaQuery(Work.class);
        if (ObjectUtils.isEmpty(model)) {
            model = new QueryWorkModel();
        }
        String title = model.getTitle();
        queryWrapper.like(StringUtils.isNotBlank(title), Work::getTitle, title);

        queryWrapper.eq(Work::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        queryWrapper.eq(!ObjectUtils.isEmpty(companyId), Work::getCompanyId, companyId);

        Page<Work> result = this.page(pageRequest, queryWrapper);
        long total = result.getTotal();
        PageVO<WorkDTO> pageVO = new PageVO<>(total, pageNo, pageSize);
        List<Work> records = result.getRecords();
        List<WorkDTO> dtoList = Collections.emptyList();
        if (!CollectionUtils.isEmpty(records)) {
            dtoList = WorkConvert.INSTANCE.workToDTOList(records);
            //遍历作业列表 查询作业和计划绑定信息和答题人数
            for (WorkDTO workDTO : dtoList) {
                //查询作业的所有答题人数
                Long workId = workDTO.getWorkId();
                int count = workRecordService.count(Wrappers.lambdaQuery(WorkRecord.class)
                        .eq(WorkRecord::getWorkId, workId));
                workDTO.setUserNum(count);
                //查询此作业的所有绑定课程名字
                RestResponse<Set<String>> restResponse = contentApiAgent.getWorkAssociationPlanName(workId);
                if (restResponse.isSuccessful()) {
                    Set<String> courseNameList = restResponse.getResult();
                    ArrayList<String> list = new ArrayList<>(courseNameList);
                    workDTO.setBindCourses(list);
                }
            }
        }
        pageVO.setItems(dtoList);
        return pageVO;
    }

    /**
     * <p>
     * 教师添加或删除作业信息
     * </p>
     *
     * @param workDTO 作业信息封装
     * @return WorkDTO
     */
    @Override
    @Transactional
    public WorkDTO createOrModifyWork(WorkDTO workDTO) {

        Long workId = workDTO.getWorkId();
        //查询作业是否存在
        Work work = this.getById(workId);

        if (ObjectUtils.isEmpty(work)) {
            //不存在则创建
            work = new Work();
            work.setTitle(workDTO.getTitle());
            work.setQuestion(workDTO.getQuestion());
            work.setCompanyId(workDTO.getCompanyId());
            work.setUsername(workDTO.getUsername());
            boolean save = this.save(work);
            if (!save) {
                ExceptionCast.cast(TeachingErrorCode.E_130302);
            }

        } else {
            work = WorkConvert.INSTANCE.dtoToWork(workDTO);
            //如果存在，先判断是否被绑定了，已绑定的作业无法修改
            RestResponse<Integer> response = contentApiAgent.getTeachplanWorkCountById(workId);
            if (!response.isSuccessful()) {
                ExceptionCast.cast(TeachingErrorCode.E_132004);
            }
            Integer result = response.getResult();
            //已绑定课程计划，无法修改
            if (result > 0) {
                ExceptionCast.cast(TeachingErrorCode.E_130305);
            }
            boolean update = updateById(work);
            if (!update) {
                ExceptionCast.cast(TeachingErrorCode.E_130302);
            }
        }
        return WorkConvert.INSTANCE.workToDTO(work);
    }

    /**
     * <p>
     * 删除作业
     * </p>
     *
     * @param workId    作业id
     * @param companyId 机构id
     */
    @Override
    @Transactional
    public void removeWork(Long workId, Long companyId) {
        Work work = this.getById(workId);
        if (ObjectUtils.isEmpty(work)) {
            ExceptionCast.cast(TeachingErrorCode.E_130304);
        }
        //校验权限
        if (!ObjectUtils.nullSafeEquals(companyId, work.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //查询此作业是否被绑定了
        RestResponse<Integer> restResponse = contentApiAgent.getTeachplanWorkCountById(workId);
        if (!restResponse.isSuccessful()) {
            ExceptionCast.cast(CommonErrorCode.E_100106);
        }
        Integer count = restResponse.getResult();
        if (ObjectUtils.isEmpty(count)) {
            ExceptionCast.cast(TeachingErrorCode.E_130302);
        }
        if (count > 0) {
            ExceptionCast.cast(TeachingErrorCode.E_130302);
        }
        LambdaUpdateWrapper<Work> updateWrapper = Wrappers.lambdaUpdate(Work.class)
                .eq(Work::getId, workId)
                .set(Work::getStatus, CommonEnum.DELETE_FLAG.getCodeInt())
                .set(Work::getChangeDate, LocalDateTime.now());

        boolean update = this.update(updateWrapper);
        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130302);
        }
    }

    /**
     * <p>
     * 提供微服务远程调用 绑定作业后修改作业信息
     * </p>
     *
     * @param params 参数封装 courseId cname teachplanId pname
     * @param workId 作业id
     * @return RestResponse
     */
    @Override
    @Transactional
    public RestResponse modifyWorkInfo(Map<String, Object> params, Long workId) {

        Integer courseId = (Integer) params.get("courseId");
        String cname = (String) params.get("cname");
        Integer teachplanId = (Integer) params.get("teachplanId");
        String pname = (String) params.get("pname");

        LambdaUpdateWrapper<Work> wrapper = Wrappers.lambdaUpdate(Work.class)
                .eq(Work::getId, workId)
                .set(Work::getCourseId, courseId)
                .set(Work::getCourseName, cname)
                .set(Work::getTeachplanId, teachplanId)
                .set(Work::getTeachplanName, pname)
                .set(Work::getChangeDate, LocalDateTime.now());
        boolean update = this.update(wrapper);
        if (!update) {
            RestResponse.validfail(TeachingErrorCode.E_130411);
        }

        return RestResponse.success();
    }

    /**
     * <p>
     * 正则校验分页参数
     * </p>
     *
     * @param str 数据字符串
     * @return boolean
     */
    private static boolean isNotPositiveNumeric(String str) {
        String regex = "^[1-9]\\d*$";
        return !str.matches(regex);
    }

}
